let number_of_color = ref 0
let interval = ref 0
let path = ref ""

(* calcul le pgcd de a et b *)
let rec pgcd a b =
  let r = a mod b in
  match r with
    | 0 -> b
    | _ -> pgcd b r

(* calcul le plus grand diviseur commun de a et b inférieur à n *)
let rec divisor a b n =
  if(n == 0) then
    1
  else
    if (a mod n = 0 & b mod n = 0) then
      n
    else
      divisor a b (n-1)

(* crée la liste des valeurs possibles d'interval *)
let creat_interval_list () =
  let map = Sdlloader.load_image !path in
  let (x,y) = SdlFunction.get_dims map in
  let rec creat_list = function
    | 1 -> []
    | i -> i::creat_list (divisor (x-1) (y-1) (i-1))
  in
  creat_list (pgcd (x-1) (y-1))

(* determine si le pixel doit etre colore en noir *)
(* renvoie la couleur d'origine du pixel ou la couleur noire *)
let getColor c b r =
  match c with
    | x when (x = b && x = r) -> c                                             
    | _ -> (0,0,0)

(* ajoute la couleur color à la liste des couleurs color_list *)
(* sauf si elle y est déjà *)
let add_color color color_list =
  if (not (List.exists (fun a -> a = color) (!color_list))) then	  
    color_list := color::(!color_list)

(* Parcours l'image, detoure les zones,
   construit la liste des couleurs *)
let build_map source map color_list =
  let (width,height) = SdlFunction.get_dims source in
    for h = 0 to height - 2 do
      for w = 0 to width - 2 do
	let color = Sdlvideo.get_pixel_color source w h in
	let colorBottom = Sdlvideo.get_pixel_color source w (h+1) in
	let colorRight = Sdlvideo.get_pixel_color source (w+1) h in
	  add_color color color_list;
	  let color = getColor color colorBottom colorRight in
	    Sdlvideo.put_pixel_color map w h color;
      done
    done
  
(* creer une chaine de caractere a partir d'un trio d'entier *)
let string_of_rgb (r,g,b) =
  "(" ^ string_of_int r ^ "," ^ string_of_int g ^ "," ^ string_of_int
    b ^ ")"

(* construit une liste d'altitude par defaut *)
(* nb_alt -> nombre d'altitudes sur la carte
   alt -> intervale entre 2 zones *)
let default_altitude nb_alt alt =
  let rec build cur_alt alt_list i =
    match i with
      | 0 -> alt_list
      | _ -> build (cur_alt + alt) (cur_alt::alt_list) (i - 1)
  in
    build 0 [] nb_alt

(* creer un fichier texte avec la liste des couleurs de la carte par
ordre croissant ainsi que le nombre de couleurs *)
let creat_txt file_name color_list altitude_list =
  let file = open_out file_name in
  begin
    output_string file (string_of_int !number_of_color);
    output_string file "\n";
    let altitude_list = ref altitude_list in
    let rec write_color = function
      | [] -> close_out file;
      | e::l -> 
	let (r,g,b) = e in
	let alt = (List.hd !altitude_list) in
	begin
	  output_string file (string_of_int r);
	  output_string file " ";
	  output_string file (string_of_int g);
	  output_string file " ";
	  output_string file (string_of_int b);
	  output_string file " ";
	  output_string file (string_of_int alt);
	  output_string file ";\n";
	  altitude_list := (List.tl !altitude_list);
	  write_color l;
	end
    in
    write_color color_list
  end
    
let rec build_color_list = function
  | (_,[])|([],_) -> ()
  | ((r,g,b)::c_l,a::alt_l) -> 
    begin
      ColorList.add (r,g,b,a);
      build_color_list (c_l,alt_l);
    end
	
(* ajoute la grille d'echantillonage sur la carte *)
let add_grid map =
  let map_grid = map in
  let (width, height) = SdlFunction.get_dims map in
  let (width, height) = (((width/(!interval))*(!interval)),
			 ((height/(!interval))*(!interval))) in
  let black = (0,0,0) in
  let h = ref 0 in
  let w = ref 0 in
  let i = ref 1 in
    (* tracage des lignes horizontales *)
    while (!h < height+1) do
      while (!w < width+1) do
	Sdlvideo.put_pixel_color map_grid !w !h black;
	w := 1 + !w;
      done;
	w := 0;
	h := !interval + !h;
    done;
      (* tracage des lignes verticales *)
      h := 0;
      while (!h < height+1) do
	while (!w < width+1) do
	  Sdlvideo.put_pixel_color map_grid !w !h black;
	  w := !interval + !w;
	done;
	  (* tracage des lignes diagonale gauche-droite *)
	  w := 0;
	  h := 1 + !h;
      done;
      h := 0;
      while (!h < height) do
	while (!w < width) do
	  Sdlvideo.put_pixel_color map_grid !w !h black;
	  w := !interval + !w;
	done;
	  h := 1 + !h;
	  w := !i;
	  if ( !i >= !interval) then
	    i := 1
	  else
	    i := 1 + !i;
      done;
      (* tracage des lignes diagonales droite-gauche *)
      w := 0;
      h := 0;
      i := !interval - 1;
      while (!h < height - 1) do
	while (!w < width - 1) do
	  Sdlvideo.put_pixel_color map_grid !w !h black;
	    w := !interval + !w;
	done;
	  h := 1 + !h;
	  w := !i;
	  if (!i <= 0) then
	    i := !interval - 1
	  else
	      i := !i - 1;
      done;
      map_grid

(* initialisation de path et de SDL *)
let init_image_processing p =
  begin
    SdlFunction.init ();
    path := p;
  end

(* fixe la valeur de l'interval *)
let set_interval source_map =
  let (x,y) = SdlFunction.get_dims source_map in
  interval := divisor (x-1) (y-1) ((pgcd (x-1) (y-1)) - 1);
  interval := divisor (x-1) (y-1) (!interval - 1)

(* crée les échantillons de couleur dans le dossier ressources
   destinés à l'interface pour la selection des altitudes *)
let create_color_sample color_list =
  let i = Sdlloader.load_image "ressources/sample.png" in
  let sample = Sdlvideo.create_RGB_surface_format i [] 1 1 in
  let rec create_s = function
    | [] -> ()
    | e::l ->
      begin
	Sdlvideo.put_pixel_color sample 0 0 e;
	let color_name = MyConvert.string_of_color e in
	Sdlvideo.save_BMP sample ("ressources/" ^ color_name ^
  ".bmp");
	create_s l;
      end
  in
  create_s color_list

(* crée une image "map.bmp" avec les contours entre les zones de
   couleurs différentes + crée le fichier "info.txt" *)
let draw_contour i =
  begin
    let source_map = Sdlloader.load_image !path in
    let contour_map = source_map in
    let color_list = ref [] in
    set_interval source_map;
    (*print_string (string_of_int !interval);*)
    interval := i;
    build_map source_map contour_map color_list;
    number_of_color := List.length !color_list;
    create_color_sample !color_list;
    let altitude_list = default_altitude !number_of_color 2 in
    Sdlvideo.save_BMP contour_map "map.bmp";
    creat_txt "info.txt" !color_list altitude_list;
    build_color_list (!color_list,altitude_list);
  end

(* crée le fichier "map_grid.bmp" *)
let draw_grid () =
  begin
    let contour_map = Sdlloader.load_image "map.bmp" in
    let map_grid = add_grid contour_map in
    Sdlvideo.save_BMP map_grid "map_grid.bmp";
    (*let img = Filtre_sobel.moy_filt contour_map in
    Sdlvideo.save_BMP img "coucou_la_map.bmp"*)
  end

